#ifndef __EPOLLPOLLER_H__
#define __EPOLLPOLLER_H__

#include "Spark/Net/Poller.h"
#include "Spark/Net/EventLoop.h"
#include <memory>
#include <array>
#include <sys/epoll.h>

enum class EpollOpt : int
{
    epADD = EPOLL_CTL_ADD,
    epMOD = EPOLL_CTL_MOD,
    epDEL = EPOLL_CTL_DEL
};

class EpollPoller : public Poller
{
    enum : int
    {
        kMaxEvents = 4096
    };
    using EventPoll = std::array<epoll_event, kMaxEvents>;

  public:
    explicit EpollPoller(EventLoop* loop);
    virtual ~EpollPoller();

  public:
    /**
     * @brief Poll and wait for events
     * @param  timeout milliseconds
     * @param  activeChannels Pointer to ChannelList
     */
    virtual void poll(int timeout, ChannelList* activeChannels) override;

    /**
     * @brief Update epoll with given Channel's fd
     * @param  ch Pointer to Channel
     */
    virtual void updateChannel(Channel* ch) override;

    /**
     * @brief Remove given Channel's fd from epoll
     * @param  ch Pointer to Channel
     */
    virtual void removeChannel(Channel* ch) override;

  private:
    /**
     * @brief Dispatch all the events from EventPoll to activeChannelList
     * @param  nEvents The number of events to traverse
     * @param  activeChannels Target activeChannelList
     */
    void dispatchEvents(int nEvents, ChannelList* activeChannels);

    /**
     * @brief Update the occured event mask for given Channel ptr
     * @param  opt
     * @param  ch Pointer to Channel
     */
    void update(EpollOpt eventMask, Channel* ch);

  private:
    int epollFD_;
    EventPoll epollEvents_{};
};

#endif  // __EPOLLPOLLER_H__